package com.thh.filesystem.uitl;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class DownloadUtil {
	
	/**
	 * @param filePath 要下载的文件路径
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	protected void download(String filePath,String returnName,HttpServletResponse response,boolean delFlag){
		this.prototypeDownload(new File(filePath), returnName, response, delFlag);
	}


	/**
	 * @param file 要下载的文件
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	protected  void download(File file,String returnName,HttpServletResponse response,boolean delFlag){
		this.prototypeDownload(file, returnName, response, delFlag);
	}
	
	/**
	 * @param file 要下载的文件
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	public static void prototypeDownload(File file,String returnName,HttpServletResponse response,boolean delFlag){
		// 下载文件
		FileInputStream inputStream = null;
		ServletOutputStream outputStream = null;
		try {
			if(!file.exists()) return;
			response.reset();
			//设置响应类型	PDF文件为"application/pdf"，WORD文件为："application/msword"， EXCEL文件为："application/vnd.ms-excel"。  
			response.setContentType("application/octet-stream;charset=utf-8");

			//设置响应的文件名称,并转换成中文编码
			//returnName = URLEncoder.encode(returnName,"UTF-8");
			returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));	//保存的文件名,必须和页面编码一致,否则乱码
			
			//attachment作为附件下载；inline客户端机器有安装匹配程序，则直接打开；注意改变配置，清除缓存，否则可能不能看到效果
			response.addHeader("Content-Disposition",   "attachment;filename="+returnName);  
			
			//将文件读入响应流
			inputStream = new FileInputStream(file);
			outputStream = response.getOutputStream();
			int length = 1024;
			int readLength=0;
			byte buf[] = new byte[1024];
			readLength = inputStream.read(buf, 0, length);
			while (readLength != -1) {
				outputStream.write(buf, 0, readLength);
				readLength = inputStream.read(buf, 0, length);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				outputStream.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		//删除原文件

		if(delFlag) {
			file.delete();
		}
		}
	}

	/**
	 * by tony 2013-10-17
	 * @param byteArrayOutputStream 将文件内容写入ByteArrayOutputStream
	 * @param response HttpServletResponse	写入response
	 * @param returnName 返回的文件名
	 */
	public static void download(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response, String returnName) throws IOException{
		response.setContentType("application/octet-stream;charset=utf-8");
		returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));			//保存的文件名,必须和页面编码一致,否则乱码
		response.addHeader("Content-Disposition",   "attachment;filename=" + returnName);  
		response.setContentLength(byteArrayOutputStream.size());
		
		ServletOutputStream outputstream = response.getOutputStream();	//取得输出流
		byteArrayOutputStream.writeTo(outputstream);					//写到输出流
		byteArrayOutputStream.close();									//关闭
		outputstream.flush();											//刷数据
	}






	static int  MAX_BUFFER_SIZE   = 1024*8;


	public static void downURL(String fileUrl, HttpServletResponse response,String returnName) {

		HttpURLConnection connection = null;
		InputStream inputStream = null;
		RandomAccessFile randomAccessFile = null;

		//路径名加上文件名加上后缀名 = 整个文件下载路径
		//String fullPathName = downloadPath+fileName+"."+SuffixName;
		ByteArrayOutputStream bos = null;
		try {
			bos =new ByteArrayOutputStream();
			// 1.获取连接对象
			URL url = new URL(fileUrl);
			// 获取链接对象，就是靠这个对象来获取流
			connection = (HttpURLConnection) url.openConnection();
			// Range代表读取的范围，bytes=0-代表从0字节到最大字节，意味着读取所有资源
			connection.setRequestProperty("Range", "bytes=0-");
			// 与网页建立链接，链接成功后就可以获得流；
			connection.connect();
			// 如果建立链接返回的相应代码是200到300间就为成功，否则链接失败,结束函数
			if (connection.getResponseCode() / 100 != 2) {
				System.out.println("连接失败...");
				return;
			}
			// 2.获取连接对象的流
			inputStream = connection.getInputStream();
			// 已下载的大小 下载进度
			int downloaded = 0;
			// 总文件的大小
			int fileSize = connection.getContentLength();
			// getFile获取此URL的文件名。返回的文件部分将与getPath（）相同,具体视频链接的文件名字视情况而定
			// String fileName = url.getFile();
			// fileName = fileName.substring(fileName.lastIndexOf("/") + 1);//特殊需要截取文件名字
			// 3.把资源写入文件
			//randomAccessFile = new RandomAccessFile(fullPathName, "rw");
			while (downloaded < fileSize) {

				// 3.1设置缓存流的大小
				//判断当前剩余的下载大小是否大于缓存之，如果不大于就把缓存的大小设为剩余的。
				byte[] buffer = null;
				if (fileSize - downloaded >= MAX_BUFFER_SIZE) {
					buffer = new byte[MAX_BUFFER_SIZE];
				} else {
					buffer = new byte[fileSize - downloaded];
				}
				// 3.2把每一次缓存的数据写入文件
				int read = -1;
				int currentDownload = 0;
				long startTime = System.currentTimeMillis();
				// 这段代码是按照缓存的大小，读写该大小的字节。然后循环依次写入缓存的大小，直至结束。
				// 这样的优势在于，不用让硬件频繁的写入，可以提高效率和保护硬盘吧
				while (currentDownload < buffer.length) {
					read = inputStream.read();
					buffer[currentDownload++] = (byte) read;
				}
				long endTime = System.currentTimeMillis();
				double speed = 0.0; //下载速度
				if (endTime - startTime > 0) {
					speed = currentDownload / 1024.0 / ((double) (endTime - startTime) / 1000);
				}
				downloaded += currentDownload;
				//randomAccessFile.write(buffer);
				bos.write(buffer);
				bos.flush();
				System.out.printf("下载了进度:%.2f%%,下载速度：%.1fkb/s(%.1fM/s)%n", downloaded * 1.0 / fileSize * 10000 / 100,
						speed, speed / 1000);

			}
			download(bos,response,returnName);

		} catch (MalformedURLException e) {// 具体的异常放到前面
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				//关闭资源、连接

				connection.disconnect();
				inputStream.close();
				bos.close();
				//randomAccessFile.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
